#ifndef ALMACENAMIENTO_H_
#define ALMACENAMIENTO_H_

#include <sstream>
#include <exception>
#include <list>

//para pruebas
#include <iostream>

enum TipoSerializacion {BINARIO, TEXTO};

using namespace std;

namespace Toolkit
{

class Almacenamiento
{
public:

	//TODO cambiar los char* por reninterpret_cast


	Almacenamiento (const unsigned long int &tamanoUnidad, const TipoSerializacion &tserializacion);
	virtual ~Almacenamiento();
	
	
	/**
	 * Inserta la serialización pasada en la primera posición vacía del archivo, 
	 * o al final de éste si no hay espacios. La posicion relativa donde se lo
	 * insertó es devuelta.
	 * Si el tamaño de la serialización es superior al permitido por el almacenamiento,
	 * se lanza una excepcion.
	 * */
	virtual unsigned long int guardarDato (const stringstream &serializacion);
	
	/**
	 * Inserta la serializacion pasada en la posicion indicada del archivo.
	 * Si el tamaño de la serialización es superior al permitido por el almacenamiento,
	 * se lanza una excepcion.
	 * */
	virtual void guardarDato (const stringstream &serializacion, const unsigned long int posicionDondeGuardar);
	
	/**
	 * Devuelve el elemento del archivo en la posicion especificada, en el sstream pasado, que debe estar
	 * abierto en el tipo de serializacion apropiada, y cuyo contenido será sobreescrito.
	 * Si la posición especificada está fuera del archivo, se lanza una excepcion.
	 * */
	virtual void recuperarDato (const unsigned long int posicionDondeGuardar, stringstream &resultado) const;
	
	/**
	 * Elimina el elemento en la posicion pasada del archivo y lo devuelve en el sstream pasado
	 * que debe estar abierto en el tipo de serializacion apropiada, y cuyo contenido será sobreescrito.
	 * Si la posición especificada está fuera del archivo, se lanza una excepcion.
	 * */
	virtual void eliminarDato (const long unsigned int posicionDondeEliminar, stringstream &resultado);
	
	unsigned long int getTamano () const;
	
	unsigned long int cantElementos() const;
		
protected:
	iostream* stream;
	unsigned long int tamanoUnidad;	
	unsigned long int elementos;
	unsigned long int offsetElementos;
	TipoSerializacion tserializacion;	
	
	/**
	 * Constructor que no realiza incializaciones (salvo la del tserializacion), delegandolas
	 * a las subclases.
	 * */
	Almacenamiento(const TipoSerializacion &tserializacion);	
	
};

class SerializacionInvalidaException : public exception
{
	virtual const char* what() const throw()
  	{
    	return "La serializacion pasada no puede almacenarse.";
  	}
};

class PosicionInvalidaException : public exception
{
	virtual const char* what() const throw()
  	{
    	return "Se accedió a una posición inválida del archivo.";
  	}
};

}
#endif /* ALMACENAMIENTO_H_ */
